package com.anyext.storage;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.anyext.storage.dialect.Dialect;
import com.anyext.storage.group.Group;
import com.anyext.storage.mapping.BeanWrapper;
import com.anyext.storage.mapping.Business;
import com.anyext.storage.mapping.CustomSql;
import com.anyext.storage.mapping.SqlMap;
import com.anyext.storage.router.Router;

public class StorageContext implements ApplicationContextAware {

	private StorageContext() {
	};

	private static final StorageContext	context	= new StorageContext();

	public static StorageContext getInstance() {
		return context;
	}

	private ApplicationContext	applicationContext;

	public static ApplicationContext getSpringContext() {
		return getInstance().applicationContext;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	// single instance for this application;
	private Session	session;

	public void setSession(Session session) {
		this.session = session;
	}

	public static Session getSession() {
		return getInstance().session;
	}

	private Collection<String>	dialectNames = new HashSet<String>();

	public static Collection<String> getDialectNames() {
		return getInstance().dialectNames;
	}

	public static Dialect getDialect(String dialectName) {
		return getSpringContext().getBean(dialectName, Dialect.class);
	}

	public static boolean hasDialect(String dialectName) {
		return getDialectNames().contains(dialectName);
	}

	public static void addDialectName(String dialectName) {
		getDialectNames().add(dialectName);
	}

	private Collection<String>	routerNames	= new HashSet<String>();

	public static Collection<String> getRouterNames() {
		return getInstance().routerNames;
	}

	public static Router getRouter(String routerName) {
		return getSpringContext().getBean(routerName, Router.class);
	}

	public static boolean hasRouter(String routerName) {
		return getRouterNames().contains(routerName);
	}

	public static void addRouterName(String routerName) {
		getRouterNames().add(routerName);
	}

	private Collection<String>	groupNames	= new HashSet<String>();

	public static Group getRoutingGroup() {
		String groupName = RouterHolder.getGroupName();
		Group group = getGroup(groupName);
		Router router = null;
		while ((router = group.getRouter()) != null) {
			groupName = router.doRoute(RouterHolder.getGroupCondition());
			group = getGroup(groupName);
		}
		return group;
	}

	public static Collection<String> getGroupNames() {
		return getInstance().groupNames;
	}

	public static Group getGroup(String groupName) {
		return getSpringContext().getBean(groupName, Group.class);
	}

	public static boolean hasGroup(String groupName) {
		return getGroupNames().contains(groupName);
	}

	public static void addGroupName(String groupName) {
		getGroupNames().add(groupName);
	}

	private Collection<String>	sqlMapNames	= new HashSet<String>();

	public static Collection<String> getSqlMapNames() {
		return getInstance().sqlMapNames;
	}

	public static SqlMap getSqlMap(String sqlMapName) {
		return getSpringContext().getBean(sqlMapName, SqlMap.class);
	}

	public static boolean hasSqlMap(String sqlMapName) {
		return getSqlMapNames().contains(sqlMapName);
	}

	public static void addSqlMapName(String sqlMapName) {
		getSqlMapNames().add(sqlMapName);
	}

	private Collection<String>	businessNames	= new HashSet<String>();

	public static Collection<String> getBusinessNames() {
		return getInstance().businessNames;
	}

	public static Business getBusiness(String businessName) {
		return getSpringContext().getBean(businessName, Business.class);
	}

	public static Business getBusiness(Class<?> beanClass) {
		return getBusiness(beanClass.getName());
	}

	public static boolean hasBusiness(String businessName) {
		return getBusinessNames().contains(businessName);
	}

	public static boolean hasBusiness(Class<?> beanClass) {
		return hasBusiness(beanClass.getName());
	}

	public static void addBusinessName(String businessName) {
		getBusinessNames().add(businessName);
	}

	private Map<Class<?>, BeanWrapper>	beanWrappers	= new HashMap<Class<?>, BeanWrapper>();

	public static Map<Class<?>, BeanWrapper> getBeanWrappers() {
		return getInstance().beanWrappers;
	}

	public static BeanWrapper getBeanWrapper(Class<?> beanClass) {
		return getBeanWrappers().get(beanClass);
	}

	public static void addBeanWrapper(BeanWrapper beanWrapper) {
		getBeanWrappers().put(beanWrapper.getBeanClass(), beanWrapper);
	}

	private Map<String, CustomSql>	customSqls	= new HashMap<String, CustomSql>();

	public static Map<String, CustomSql> getCustomSqls() {
		return getInstance().customSqls;
	}

	public static CustomSql getCustomSql(String sqlName) {
		return getCustomSqls().get(sqlName);
	}

	public static void addCustomSql(CustomSql customSqls) {
		getCustomSqls().put(customSqls.getIdentity(), customSqls);
	}

}
